﻿#region using statements

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using XNAGameEngine.Utility;

#endregion

namespace XNAGameEngine.Input
{
    public sealed partial class ManagerInput
    {
        #region Nested type: ManagerKeyboardInput

        /// <summary>
        /// This class handles the updating and event throwing of the keyboard
        /// </summary>
        private sealed class ManagerKeyboardInput
        {
            #region local fields

            /// <summary>
            /// reference to the input manager
            /// </summary>
            private readonly ManagerInput _inputManager;

            #endregion

            #region properties

            /// <summary>
            /// Get the current state of the keyboard
            /// </summary>
            public KeyboardState _CurrentKeyboardState { get; private set; }

            /// <summary>
            /// Get the last state of the keyboard
            /// </summary>
            public KeyboardState _LastKeyboardState { get; private set; }

            #endregion

            #region constructors

            /// <summary>
            /// Default constructor, saves a reference to the InputManager
            /// </summary>
            /// <param name="inputManager">the input manager that creates this object</param>
            public ManagerKeyboardInput(ManagerInput inputManager)
            {
                _inputManager = inputManager;
            }

            #endregion

            #region local methods

            /// <summary>
            /// Update the input devices
            /// </summary>
            /// <param name="gameTime">the game time reference object</param>
            public void Update(GameTime gameTime)
            {
                _CurrentKeyboardState = Keyboard.GetState();

                // For every key on the keyboard
                foreach (Keys key in EnumParse.GetEnumValues<Keys>())
                {
                    // If it is a new key press throw the key pressed event
                    if (WasKeyPressed(key))
                    {
                        _inputManager.InputPressed(key, null, null, null, null);
                        continue;
                    }

                    // If it is a key release throw the key released event
                    if (WasKeyReleased(key))
                    {
                        _inputManager.InputReleased(key, null, null, null, null);
                        continue;
                    }

                    // If it is being held throw the key held event
                    if (WasKeyHeld(key))
                    {
                        _inputManager.InputHeld(key, null, null, null, null);
                        continue;
                    }
                }

                _LastKeyboardState = _CurrentKeyboardState;
            }

            /// <summary>
            /// Whether the specified key is down for the first time this frame
            /// </summary>
            /// <param name="key">the key to test</param>
            /// <returns>true if the key was pressed this frame, false otherwise</returns>
            public bool WasKeyPressed(Keys key)
            {
                return (_LastKeyboardState.IsKeyUp(key)
                        && _CurrentKeyboardState.IsKeyDown(key));
            }

            /// <summary>
            /// Whether the specified key is up for the first time this frame
            /// </summary>
            /// <param name="key">the key to test</param>
            /// <returns>true if the key was released this frame, false otherwise</returns>
            public bool WasKeyReleased(Keys key)
            {
                return (_LastKeyboardState.IsKeyDown(key)
                        && _CurrentKeyboardState.IsKeyUp(key));
            }

            /// <summary>
            /// Whether the specified key has been down for more than one frame
            /// </summary>
            /// <param name="key">the key to test</param>
            /// <returns>true if the key was held since the last frame, false otherwise</returns>
            public bool WasKeyHeld(Keys key)
            {
                return (_LastKeyboardState.IsKeyDown(key)
                        && _CurrentKeyboardState.IsKeyDown(key));
            }

            #endregion
        }

        #endregion
    }
}